home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 115_01.zip / ED10.C < prev    next >
Text File  |  1993-06-01  |  9KB  |  447 lines

  1. /* Screen editor:  buffer module
  2.  *
  3.  * Source:  ed10.c
  4.  * Version: April 7, 1981.
  5.  */
  6.  
  7. /* Define the variables global to this module.
  8.  * Buffer must be declared after all other variables
  9.  * of the entire program.
  10.  * Note: buffer must have nonzero dimension.
  11.  */
  12.  
  13. int bufcflag;        /* main buffer changed flag */
  14. char *bufp;        /* start of current line */
  15. char *bufpmax;        /* end of last line */
  16. char *bufend;        /* last byte of buffer */
  17. int bufline;        /* current line number */
  18. int bufmaxln;        /* number of lines in buffer */
  19. char buffer[1];        /* start of buffer */
  20.  
  21. /* This code is built around several invariant
  22.  * assumptions:
  23.  * First, the last line is always completely empty.
  24.  * When bufp points to the last line there is NO
  25.  * CR following it.
  26.  * Second, bufp points to the last line if and only if
  27.  * bufline==bufmaxln+1.
  28.  * Third, bufline is always greater than zero.
  29.  * Line zero exists only to make scanning for the
  30.  * start of line one easier.
  31.  */
  32.  
  33.  
  34. /* Clear the main buffer */
  35.  
  36. bufnew()
  37. {
  38.     /* point past line 0 */
  39.     bufp=bufpmax=buffer+1;
  40.     /* point at last byte of buffer */
  41.     /* allow space for stack */
  42.     bufend=sysend()-1000;
  43.     /* at line one. no lines in buffer */
  44.     bufline=1;
  45.     bufmaxln=0;
  46.     /* line zero is always a null line */
  47.     buffer[0]=CR;
  48.     /* indicate no need to save file yet */
  49.     bufcflag=NO;
  50. }
  51.  
  52. /* return current line number */
  53.  
  54. bufln()
  55. {
  56.     return(bufline);
  57. }
  58.  
  59. /* return YES if the buffer (i.e., file) has been
  60.  * changed since the last time the file was saved.
  61.  */
  62.  
  63. bufchng()
  64. {
  65.     return(bufcflag);
  66. }
  67.  
  68. /* the file has been saved.  clear bufcflag. */
  69.  
  70. bufsaved()
  71. {
  72.     bufcflag=NO;
  73. }
  74.  
  75. /* return number of bytes left in the buffer */
  76.  
  77. buffree()
  78. {
  79.     return(bufend-bufp);
  80. }
  81.  
  82. /* Position buffer pointers to start of indicated line */
  83.  
  84. bufgo(line) int line;
  85. {
  86.     /* put request into range. prevent extension */
  87.     line=min(bufmaxln+1,line);
  88.     line=max(1,line);
  89.     /* already at proper line? return. */
  90.     if (line==bufline) {
  91.         return(OK);
  92.     }
  93.     /* move through buffer one line at a time */
  94.     while (line<bufline) {
  95.         if (bufup()==ERR) {
  96.             return(ERR);
  97.         }
  98.     }
  99.     while (line>bufline) {
  100.         if (bufdn()==ERR) {
  101.             return(ERR);
  102.         }
  103.     }
  104.     /* we have reached the line we wanted */
  105.     return(OK);
  106. }
  107.  
  108. /* move one line closer to front of buffer, i.e.,
  109.  * set buffer pointers to start of previous line.
  110.  */
  111.  
  112. bufup()
  113. {
  114. char *oldbufp;
  115.     oldbufp=bufp;
  116.     /* can't move past line 1 */
  117.     if (bufattop()) {
  118.         return(OK);
  119.     }
  120.     /* move past CR of previous line */
  121.     if (*--bufp!=CR) {
  122.         syserr("bufup: missing CR");
  123.         bufp=oldbufp;
  124.         return(ERR);
  125.     }
  126.     /* move to start of previous line */
  127.     while (*--bufp!=CR) {
  128.         ;
  129.     }
  130.     bufp++;
  131.     /* make sure we haven't gone too far */
  132.     if (bufp<(buffer+1)) {
  133.         syserr("bufup: bufp underflow");
  134.         bufp=oldbufp;
  135.         return(ERR);
  136.     }
  137.     /* success!  we ARE at previous line */
  138.     bufline--;
  139.     return(OK);
  140. }
  141.  
  142. /* Move one line closer to end of buffer, i.e.,
  143.  * set buffer pointers to start of next line.
  144.  */
  145.  
  146. bufdn()
  147. {
  148. char *oldbufp;
  149.     oldbufp=bufp;
  150.     /* do nothing silly if at end of buffer */
  151.     if (bufatbot()) {
  152.         return(OK);
  153.     }
  154.     /* scan past current line and CR */
  155.     while (*bufp++!=CR) {
  156.         ;
  157.     }
  158.     /* make sure we haven't gone too far */
  159.     if (bufp>bufpmax) {
  160.         syserr("bufdn: bufp overflow");
  161.         bufp=oldbufp;
  162.         return(ERR);
  163.     }
  164.     /* success! we are at next line */
  165.     bufline++;
  166.     return(OK);
  167. }
  168.  
  169. /* Insert a line before the current line.
  170.  * p points to a line of length n to be inserted.
  171.  * Note: n does not include trailing CR.
  172.  */
  173.  
  174. bufins(p,n) char *p; int n;
  175. {
  176. int k;
  177.     /* make room in the buffer for the line */
  178.     if (bufext(n+1)==ERR) {
  179.         return(ERR);
  180.     }
  181.     /* put the line and CR into the buffer */
  182.     k=0;
  183.     while (k<n) {
  184.         *(bufp+k)=*(p+k);
  185.         k++;
  186.     }
  187.     *(bufp+k)=CR;
  188.     /* increase number of lines in buffer */
  189.     bufmaxln++;
  190.     /* special case: inserting a null line at
  191.      * end of file is not a significant change.
  192.      */
  193.     if ((n==0)&(bufnrbot())) {
  194.         ;
  195.     }
  196.     else {
  197.         bufcflag=YES;
  198.     }
  199.     return(OK);
  200. }
  201.  
  202. /* delete the current line */
  203.  
  204. bufdel()
  205. {
  206.     return(bufdeln(1));
  207. }
  208.  
  209. /* delete n lines, starting with the current line */
  210.  
  211. bufdeln(n) int n;
  212. {
  213. int oldline;
  214. int k;
  215. char *oldbufp;
  216.     /* remember current buffer parameters */
  217.     oldline=bufline;
  218.     oldbufp=bufp;
  219.     /* scan for first line after deleted lines */
  220.     k=0;
  221.     while ((n--)>0) {
  222.         if (bufatbot()) {
  223.             break;
  224.         }
  225.         if (bufdn()==ERR) {
  226.             bufline=oldline;
  227.             oldbufp=bufp;
  228.             return(ERR);
  229.         }
  230.         k++;
  231.     }
  232.     /* compress buffer.  update pointers */
  233.     bufmovup(bufp,bufpmax-1,bufp-oldbufp);
  234.     bufpmax=bufpmax-(bufp-oldbufp);
  235.     bufp=oldbufp;
  236.     bufline=oldline;
  237.     bufmaxln=bufmaxln-k;
  238.     bufcflag=YES;
  239.     return(OK);
  240. }
  241.  
  242. /* replace current line with the line that
  243.  * p points to.  The new line is of length n.
  244.  */
  245.  
  246. bufrepl(p,n) char *p; int n;
  247. {
  248. int oldlen, k;
  249. char *nextp;
  250.     /* do not replace null line.  just insert */
  251.     if (bufatbot()) {
  252.         return(bufins(p,n));
  253.     }
  254.     /* point nextp at start of next line */
  255.     if (bufdn()==ERR) {
  256.         return(ERR);
  257.     }
  258.     nextp=bufp;
  259.     if (bufup()==ERR) {
  260.         return(ERR);
  261.     }
  262.     /* allow for CR at end */
  263.     n=n+1;
  264.     /* see how to move buffer below us;
  265.      * up, down, or not at all.
  266.      */
  267.     oldlen=nextp-bufp;
  268.     if (oldlen<n) {
  269.         /* move buffer down */
  270.         if (bufext(n-oldlen)==ERR) {
  271.             return(ERR);
  272.         }
  273.         bufpmax=bufpmax+n-oldlen;
  274.     }
  275.     else if (oldlen>n) {
  276.         /* move buffer up */
  277.         bufmovup(nextp,bufpmax-1,oldlen-n);
  278.         bufpmax=bufpmax-(oldlen-n);
  279.     }
  280.     /* put new line in the hole we just made */
  281.     k=0;
  282.     while (k<(n-1)) {
  283.         bufp[k]=p[k];
  284.         k++;
  285.     }
  286.     bufp[k]=CR;
  287.     bufcflag=YES;
  288.     return(OK);
  289. }
  290.  
  291. /* copy current line into buffer that p points to.
  292.  * the maximum size of that buffer is n.
  293.  * return k=length of line in the main buffer.
  294.  * if k>n then truncate n-k characters and only
  295.  * return n characters in the caller's buffer.
  296.  */
  297.  
  298. bufgetln(p,n) char *p; int n;
  299. {
  300. int k;
  301.     /* last line is always null */
  302.     if (bufatbot()) {
  303.         return(0);
  304.     }
  305.     /* copy line as long as it not too long */
  306.     k=0;
  307.     while (k<n) {
  308.         if (*(bufp+k)==CR) {
  309.             return(k);
  310.         }
  311.         *(p+k)=*(bufp+k);
  312.         k++;
  313.     }
  314.     /* count length but move no more chars */
  315.     while (*(bufp+k)!=CR) {
  316.         k++;
  317.     }
  318.     return(k);
  319. }
  320.  
  321. /* move buffer down (towards HIGH addresses) */
  322.  
  323. bufmovdn(from,to,length) char *from, *to; int length;
  324. {
  325.     /* this code needs to be very fast.
  326.      * use an assembly language routine.
  327.      */
  328.     sysmovdn(to-from+1,to+length,to);
  329. }
  330.  
  331. /* the call to sysmovdn() is equivalent to the following code:
  332.  
  333. int k;
  334.     k=to-from+1;
  335.     while ((k--)>0) {
  336.         *(to+length)=*to;
  337.         to--;
  338.     }
  339.  
  340.  */
  341.  
  342. /* move buffer up (towards LOW addresses) */
  343.  
  344. bufmovup(from,to,length) char *from, *to; int length;
  345. {
  346.     /* this code must be very fast.
  347.      * use an assembly language routine.
  348.      */
  349.     sysmovup(to-from+1,from-length,from);
  350. }
  351.  
  352. /* the call to sysmovup() is equivalent to the following code:
  353.  
  354. int k;
  355.     k=to-from+1;
  356.     while ((k--)>0) {
  357.         *(from-length)=*from;
  358.         from++;
  359.     }
  360.  
  361.  */
  362.  
  363. /* return true if at bottom of buffer.
  364.  * NOTE 1: the last line of the buffer is always null.
  365.  * NOTE 2: the last line number is always bufmaxln+1.
  366.  */
  367.  
  368. bufatbot()
  369. {
  370.     return(bufline>bufmaxln);
  371. }
  372.  
  373. /* return true if at bottom or at the last
  374.  * real line before the bottom.
  375.  */
  376.  
  377. bufnrbot()
  378. {
  379.     return(bufline>=bufmaxln);
  380. }
  381.  
  382. /* return true if at top of buffer */
  383.  
  384. bufattop()
  385. {
  386.     return(bufline==1);
  387. }
  388.  
  389. /* put nlines lines from buffer starting with
  390.  * line topline at position topy of the screen.
  391.  */
  392.  
  393. bufout(topline,topy,nlines) int topline, topy, nlines;
  394. {
  395. int l,p;
  396.     /* remember buffer's state */
  397.     l=bufline;
  398.     p=bufp;
  399.     /* write out one line at a time */
  400.     while ((nlines--)>0) {
  401.         outxy(0,topy++);
  402.         bufoutln(topline++);
  403.     }
  404.     /* restore buffer's state */
  405.     bufline=l;
  406.     bufp=p;
  407. }
  408.  
  409. /* print line of main buffer on screen */
  410.  
  411. bufoutln(line) int line;
  412. {
  413.     /* error message does NOT go on prompt line */
  414.     if (bufgo(line)==ERR) {
  415.         fmtsout("disk error: line deleted",0);
  416.         outdeol();
  417.         return;
  418.     }
  419.     /* blank out lines below last line of buffer */
  420.     if (bufatbot()) {
  421.         outdeol();
  422.     }
  423.     /* write one formatted line out */
  424.     else {
  425.         fmtsout(bufp,0);
  426.         outdeol();
  427.     }
  428. }
  429.  
  430. /* simple memory version of bufext.
  431.  * create a hole in buffer at current line.
  432.  * length is the size of the hole.
  433.  */
  434.  
  435. bufext(length) int length;
  436. {
  437.     /* make sure there is room for more */
  438.     if ((bufpmax+length)>=bufend) {
  439.         error("main buffer is full");
  440.         return(ERR);
  441.     }
  442.     /* move lines below current line down */
  443.     bufmovdn(bufp,bufpmax-1,length);
  444.     bufpmax=bufpmax+length;
  445.     return(OK);
  446. }
  447.